package com.yc.cinema.mybatis;

import org.apache.ibatis.annotations.Select;

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class SqlSession {

    public <T> T getMapper(Class<T> clss){
        // 基于 JDK 动态代理
        // InvocationHandler 方法拦截器
        Object o = Proxy.newProxyInstance(
                clss.getClassLoader(), //类加载器
                new Class[]{clss}, //类接口数组
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                        System.out.println("proxy = " + proxy);
                        System.out.println("method = " + method);
                        System.out.println("args = " + Arrays.toString(args));

                        //使用反射获取方法上的注解(select)
                        Select select = method.getAnnotation(Select.class);
                        // 获取SQL语句
                        String[] value = select.value();
                        String sql = value[0];
                        // 提取sql中的参数值
                        int index = 0;
                        // 参数集合
                        List<Object> params = new ArrayList<>();
                        while( (index = sql.indexOf("#{")) > -1){
                            // 查找右 }
                            int endIndex = sql.indexOf("#}",index);
                            String name = sql.substring(index + 2,endIndex);
                            // 提起方法参数中的 指定的 name 值
                            // 如果方法只有一个 简单基本数据类型(或String)参数
                            if (method.getParameters().length == 1){
                                //单个参数
                                Parameter parameter = method.getParameters()[0];
                                // isPrimitive() 基本数据类型 int,char..
                                if (parameter.getType().isPrimitive()
                                        || parameter.getType() == String.class
                                        // || 包装器类型 Integer
                                        )  {
                                    params.add(args[0]);
                                } else {
                                    // 否则就是对象参数 Hall, Movie
                                    // 通过反射获取参数值
                                    Field field = args[0].getClass().getField(name);
                                    field.setAccessible(true); // 设置强制访问 , private
                                    Object val = field.get(args[0]);
                                    params.add(val);
                                }
                            } else {
                                // 多个参数

                            }

                        }

                        // 将SQL中的#{...} 替换成 ?
                        sql = sql.replaceAll("#\\{\\w+\\}","?");
                        System.out.println("sql = " + sql);

                        //DBHelper 执行 查询, 语句sql , 参数数组:params.toString参数

                        return null;
                    }
                }
        );
        return (T) o ;
    }
}
